package cn.edu.fzu.homemaking.company.handler.impl;

import cn.edu.fzu.homemaking.company.domain.entity.CompanyUser;
import cn.edu.fzu.homemaking.company.filter.order.OrderFilter;
import cn.edu.fzu.homemaking.company.filter.order.OrderFilterDto;
import cn.edu.fzu.homemaking.company.handler.OrderError;
import cn.edu.fzu.homemaking.company.handler.OrderHandler;
import cn.edu.fzu.homemaking.company.handler.OrderSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Component("orderUserFilterHandler")
public class OrderUserFilterHandler implements OrderHandler {

    private static final Logger    log = LoggerFactory.getLogger(OrderUserFilterHandler.class);

    @Resource
    private List<OrderFilter>      orderFilters;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public boolean process(OrderSession session) {
        final OrderFilterDto dto = new OrderFilterDto();

        // 构建一个为服务员过滤器准备数据的任务队列
        List<Callable<Boolean>> tasks = new ArrayList<>(orderFilters.size());
        for (final OrderFilter item : orderFilters) {
            tasks.add(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return item.prepare(session, dto);

                }
            });
        }

        // 并行执行任务
        List<Future<Boolean>> futures;
        try {
            futures = threadPoolTaskExecutor.getThreadPoolExecutor().invokeAll(tasks, 3000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            session.error = OrderError.SYS_ERROR;
            return false;
        }

        OrderFilter filter;
        List<OrderFilter> filters = new LinkedList<>();
        for (int i = 0; i < orderFilters.size(); i++) {
            filter = orderFilters.get(i);
            try {
                if (futures.get(i).get()) {
                    filters.add(filter);
                }
            } catch (Exception e) {
                log.error("company user filter handle error.", e);
            }
        }

        CompanyUser user;
        Iterator<CompanyUser> it = session.companyUsers.iterator();
        while (it.hasNext()) {
            user = it.next();
            for (OrderFilter item : filters) {
                if (item.filter(user, dto)) {
                    log.info("filter user:{},filter name :{}",user.getName(),item.getClass().getName());
                    it.remove();
                    break;
                }
            }
        }

        if (session.companyUsers.isEmpty()) {
            session.error = OrderError.NO_USER;
            return false;
        }

        return true;
    }
}
